<template>
  <div class="page-container">
    <div style="width: 100%; height: 100%">
      <div id="container"></div>
    </div>
  </div>
</template>

<script>
import { Graph, Node, Edge, Shape, Line, Path, Curve } from "@antv/x6";
import { register } from "@antv/x6-vue-shape";
import Hierarchy from "@antv/hierarchy";
import TreeNode from "./treeNode.vue";
import ContentNode from "./contentNode.vue";
import MethodNode from "./methodNode.vue";
import mockList from "./mock";

export default {
  data() {
    return {
      graph: null,
    };
  },
  methods: {
    // 初始化画板
    initGraph() {
      const container = document.getElementById("container");
      this.graph = new Graph({
        container: container,
        // width: container.offsetWidth,
        // height: container.offsetHeight,
        // autoResize: true, // 自适应
        // panning: true, // 鼠标按下画布后移动时会拖拽画布，
        // mousewheel: true, // 滚动鼠标滚轮会缩放画布。
        // snapline: true, // 对齐线
        background: {
          color: "#F2F7FA",
        },

        grid: {
          visible: true,
          type: "doubleMesh",
          args: [
            {
              color: "#eee", // 主网格线颜色
              thickness: 1, // 主网格线宽度
            },
            {
              color: "#ddd", // 次网格线颜色
              thickness: 1, // 次网格线宽度
              factor: 4, // 主次网格线间隔
            },
          ],
        },
      });
      // 下面为画布增加对齐线功能，当移动的节点与其他节点对齐时，会自动出现对齐线，可以方便用户进行位置排版。
      //   this.graph.use(
      //     new Snapline({
      //       enabled: true,
      //     })
      //   );
    },
    // 注册
    regesterGraph() {
      register({
        shape: "tree-node",
        width: 140,
        height: 40,
        component: {
          render: (h) =>
            h(TreeNode, {
              on: {
                expandChildren: (type, cnode) => {
                  // this.updateData(type, cnode);
                },
              },
            }),
        },
        ports: {
          groups: {
            left: {
              position: "left",
              attrs: {
                circle: {
                  display: "none",
                  r: 6,
                  magnet: true,
                  stroke: "#1f89cc",
                  strokeWidth: 2,
                  fill: "#fff",
                },
              },
            },
            right: {
              position: "right",
              attrs: {
                circle: {
                  display: "none",
                  r: 6,
                  magnet: true,
                  stroke: "#1f89cc",
                  strokeWidth: 2,
                  fill: "#fff",
                },
              },
            },
          },
        },
      });
      register({
        shape: "target-node",
        width: 280,
        height: 136,
        component: {
          render: (h) =>
            h(ContentNode, {
              on: {
                expandChildren: (data, a) => {
                  console.log(data, a);
                },
              },
            }),
        },
        ports: {
          groups: {
            left: {
              position: "left",
              attrs: {
                circle: {
                  display: "none",
                  r: 6,
                  magnet: true,
                  stroke: "#1f89cc",
                  strokeWidth: 2,
                  fill: "#fff",
                },
              },
            },
            right: {
              position: "right",
              attrs: {
                circle: {
                  display: "none",
                  r: 6,
                  magnet: true,
                  stroke: "#1f89cc",
                  strokeWidth: 2,
                  fill: "#fff",
                },
              },
            },
          },
        },
      });
      register({
        shape: "method-node",
        width: 140,
        height: 60,
        component: {
          render: (h) =>
            h(MethodNode, {
              on: {
                change: (data, a) => {
                  console.log(data, a);
                },
              },
            }),
        },
        ports: {
          groups: {
            left: {
              position: "left",
              attrs: {
                circle: {
                  display: "none",
                  r: 6,
                  magnet: true,
                  stroke: "#1f89cc",
                  strokeWidth: 2,
                  fill: "#fff",
                },
              },
            },
          },
        },
      });
      // 边
      Graph.registerEdge(
        "model-edge",
        {
          inherit: "edge",
          attrs: {
            line: {
              stroke: "#004892",
              strokeWidth: 1,
              targetMarker: {
                name: "classic",
              },
              // targetMarker: {
              //   tagName: "path",
              //   fill: "yellow", // 使用自定义填充色
              //   stroke: "green", // 使用自定义边框色
              //   strokeWidth: 2,
              //   d: "M 20 -10 0 0 20 10 Z",
              // },
            },
          },
          // connector: {
          //   name: "smooth",
          // },
          zIndex: 0,
        },
        true
      );

      Graph.registerConnector(
        "multi-smooth",
        (sourcePoint, targetPoint, routePoints, options) => {
          const { index = 0, total = 1, gap = 12 } = options;
          const line = new Line(sourcePoint, targetPoint);
          const centerIndex = (total - 1) / 2;
          const dist = index - centerIndex;
          const diff = Math.abs(dist);
          const factor = diff === 0 ? 1 : diff / dist;
          const vertice = line
            .pointAtLength(line.length() / 2 + gap * factor * Math.ceil(diff))
            .rotate(90, line.getCenter());

          const points = [sourcePoint, vertice, targetPoint];
          const curves = Curve.throughPoints(points);
          const path = new Path(curves);
          return options.raw ? path : path.serialize();
        },
        true
      );
    },
    // 标记数据
    markData() {
      console.log("mockList", mockList);
      const treeData = {
        label: "root",
        type: "root",
        id: "root",
        data: {}, // api  节点私有数据
        children: mockList,
      };
      // 给树形结构绑定一些字段
      const markTree = (treeList, zIndex = 1) => {
        treeList.forEach((node) => {
          console.log("node", node);
          node.shape = getShapeByZIndex(zIndex); // 处理层级与 节点Type
          
          if (node.children) {
            markTree(node.children, zIndex + 1);
          }
        });
      };

      const getShapeByZIndex = (zIndex) => {
        let shape;
        console.log("zIndex", zIndex);
        switch (zIndex) {
          // 根节点
          case 1: {
            shape = "root";
            break;
          }
          // 树形节点
          case 2: {
            shape = "tree-node";
            break;
          }
        }
        return shape;
      };

      markTree([treeData], 1);

      return treeData;
    },
    render() {
      const graph = this.graph;
      const data = this.markData();

      const result = Hierarchy.mindmap(data, {
        direction: "H",
        getHeight(d) {
          return 20;
        },
        getWidth(d) {
          return 40;
        },
        getHGap() {
          return 120;
        },
        getVGap() {
          return 110;
        },
        getSide: () => {
          return "right";
        },
      });
      const model = {
        nodes: [],
        edges: [],
      };
      const traverse = (hierarchyItem) => {
        console.log("hierarchyItem", hierarchyItem);
        const { data } = hierarchyItem;
        //   model.nodes?.push({
        //   id: `${data.id}`,
        //   x: data.x + 250,
        //   y: data.y + 250,
        //   shape: 'circle',
        //   width: 16,
        //   height: 16,
        //   attrs: {
        //     body: {
        //       fill: '#5F95FF',
        //       stroke: 'transparent',
        //     },
        //   },
        // })
      };

      traverse(result);
    },
  },
  mounted() {
    this.initGraph();
    this.regesterGraph();
    this.render();
  },
};
</script>

<style lang="scss" scoped>
.page-container {
  width: 100%;
  height: 100%;
  border: 1px solid red;
  #container {
    width: 800px;
    height: 600px;
  }
}
</style>
